﻿package {
	import flash.display.DisplayObjectContainer;
	import flash.display.Graphics;
	import flash.display.GraphicsPath;
	import flash.display.GraphicsPathCommand;
	import flash.display.GraphicsSolidFill;
	import flash.display.GraphicsStroke;
	import flash.display.IGraphicsData;
	import flash.display.IGraphicsStroke;
	import flash.display.MovieClip;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Vector3D;
	import flash.utils.getTimer;
	
	[SWF(width=400, height=400, backgroundColor=0xDBD3AE, frameRate=30)]
	public class Main5 extends Sprite {
		private var main	:Shape;
		private var rootObj	:Object;
		private var count		:int;
		private var directionVector		:Vector3D;
		private var rootRotation		:int = 0;
		
		public function Main5():void
		{
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			main = addChild(new Shape()) as Shape;
			main.transform.matrix = new Matrix(-1, 0, 0, -1, Math.round(stage.stageWidth / 2), stage.stageHeight - 0);

			stage.addEventListener(Event.ENTER_FRAME, redraw);
			stage.addEventListener(MouseEvent.CLICK, doStart);
			doStart();
		}
		
		public function redraw(e:Event = null):void  {
			main.graphics.clear();
			rootRotation+=3;
			updateLine(rootObj, new Vector3D(0, 1, 0));
		}

		public function doStart(e:Event = null):void  {rootObj = {level:1, i:0, age:int(0), posRandom:1, maxage:200, rotationZ:90, maxlength:stage.stageHeight*5, parentObj:{rotationY:0, rotationZ:90, posRandom:1, length:0} };}
		
		public function updateLine(thisObj:Object, sumVector:Vector3D):void {
			var configObj:Object = {maxlength: (thisObj.maxlength == undefined && thisObj.parentObj.maxlength != undefined)? Math.round(thisObj.parentObj.maxlength * 0.9 * (1 - thisObj.posRandom * 0.4)) : false, rotationY: (thisObj.rotationY == undefined)? (thisObj.parentObj.rotationY + Math.round( Math.random() * 360)) % 360 : false, rotationZ: (thisObj.rotationZ == undefined)? thisObj.parentObj.rotationZ + Math.round( 35 + Math.random() * 15) * (Math.round(Math.random()) * 2 - 1) : false, age: (thisObj.age < thisObj.maxage)? thisObj.age+1 : thisObj.age, length: (thisObj.maxlength == undefined)? 0 : (thisObj.maxlength * Math.sin(thisObj.age/thisObj.maxage * (Math.PI/2))) };
			for (var itemName:String in configObj) { if(itemName == "age" || itemName == "length" || (thisObj[itemName] == undefined && configObj[itemName] != false)) thisObj[itemName] = configObj[itemName] };
			
			var currentVector:Vector3D = new Vector3D(Point.polar(Point.polar(1, thisObj.rotationZ * Math.PI / 180).x*thisObj.length/10, (thisObj.rotationY + rootRotation) * Math.PI / 180).x, Point.polar(1, thisObj.rotationZ * Math.PI / 180).y*thisObj.length/10, Point.polar(Point.polar(1, thisObj.rotationZ * Math.PI / 180).x, (thisObj.rotationY + rootRotation) * Math.PI / 180).y*thisObj.length/10 );
			var parentVector:Vector3D = new Vector3D(Point.polar(Point.polar(1, thisObj.parentObj.rotationZ * Math.PI / 180).x*(thisObj.parentObj.length/10 * thisObj.posRandom), (thisObj.parentObj.rotationY + rootRotation) * Math.PI / 180).x, Point.polar(1, thisObj.parentObj.rotationZ * Math.PI / 180).y*(thisObj.parentObj.length/10 * thisObj.posRandom), Point.polar(Point.polar(1, thisObj.parentObj.rotationZ * Math.PI / 180).x, (thisObj.parentObj.rotationY + rootRotation) * Math.PI / 180).y*(thisObj.parentObj.length/10 * thisObj.posRandom) );
		
			parentVector.incrementBy(sumVector);
			currentVector.incrementBy(parentVector);
			
			main.graphics.moveTo( parentVector.x, parentVector.y );
			main.graphics.lineStyle(thisObj.length / (80 + thisObj.i * 10), 0x3E2809 );
			main.graphics.lineTo( currentVector.x, currentVector.y );

			if (thisObj.age > thisObj.maxage / 8 && thisObj.length > 30 && thisObj.level < 6) {
				if (thisObj.child0 == null) for (var i:int = (thisObj.level < 3)? 5-i:2; i >= 0; i--) { thisObj["child" + i] = {parentObj:thisObj, level:thisObj.level+1, i:i, age:0, posRandom: (i == 0) ? 1 : 1 - i * 0.1 - Math.round(Math.random() * 2) / 10, maxage: Math.round(thisObj.maxage * (0.99 + Math.random() * 0.2))  }};
				for (var j:int = 0; thisObj["child"+j] != null; j++) updateLine(thisObj["child"+j], parentVector);
			}
		}
	}
}